home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
LISP
/
XLISP_TO
/
MEDICAL_
/
ADX.LSP
next >
Wrap
Lisp/Scheme
|
1990-04-21
|
45KB
|
1,233 lines
;***** XLISP VERSION 21/04/90 ******
(defvar *all-dd* nil)
(defvar *all-disease* nil) ;current dd-structs
(defvar *dd-list* nil)
(defvar *disease-list* nil) ;current dd's
(defvar *dd-slots* '(symptom diseases d-slot)) ;slots of struct dd
(defvar *symptom-list* nil) ;symptoms for search-a-disease
(defvar *probable-diseases* nil) ;resulting diseases from search
(defvar *age-probable* nil) ;diseases within age-group
(defvar *morbidity-list* nil) ;diseases with morbidity-data
(defvar *disease-slots* ;slots of struct disease
'(name ; morbidity geographic-occurrence
age-groups
sex-predominance ; m 0.6 f 0.4
clinical-symptoms
lab-findings ; labtest: values [no-values] expl cost
rx-findings ; Sy : method frequency expl cost
sites
therapy ; method:dosage time controls complications
follow-up
prognosis-and-complications
literature ; ti au publ
diff-diag ; other diseases: differentiation to act
general-description
property-slot
codes
reserve1 reserve2 reserve3 reserve4 reserve5))
(defvar *prop-list* '(freq explanation methods normal-values cost time
morbidity geographic-occurrence dosage
overdose-reactions)) ;possible properties of slots
(defvar *all-symptoms* nil)
(defvar *all-symptoms-string* nil)
(defvar *flag* nil)
(defvar *line-cnt* 0)
(defvar *struct* nil)
(defvar *test-struct* nil)
(defvar *all-string-list* nil)
(defmacro pop (stack)
`(let ((x (car ,stack)))
(setq ,stack (cdr ,stack))
x))
(defmacro push (thing stack)
`(setq ,stack (cons ,thing ,stack)))
;****** accessors *********
(defmacro symptom (dd) `(car ,dd))
(defmacro diseases (dd) `(car (cdr ,dd)))
(defmacro d-slot (dd) `(car (cddr ,dd)))
(defmacro name (disease) `(car ,disease))
(defmacro age-groups (disease) `(car (cdr ,disease)))
(defmacro sex-predominance (disease) `(car (cddr ,disease)))
(defmacro clinical-symptoms (disease) `(car (cdddr ,disease)))
(defmacro lab-findings (disease) `(car (cddddr ,disease)))
(defmacro rx-findings (disease) `(car (cdr (cddddr ,disease))))
(defmacro sites (disease) `(car (cddr (cddddr ,disease))))
(defmacro therapy (disease) `(car (cdddr (cddddr ,disease))))
(defmacro follow-up (disease) `(car (cddddr (cddddr ,disease))))
(defmacro prognosis-and-complications (disease)
`(car (cdr (cddddr (cddddr ,disease)))))
(defmacro literature (disease) `(car (cddr (cddddr (cddddr ,disease)))))
(defmacro diff-diag (disease) `(car (cdddr (cddddr (cddddr ,disease)))))
(defmacro general-description (disease)
`(car (cddddr (cddddr (cddddr ,disease)))))
(defmacro property-slot (disease)
`(car (cdr (cddddr (cddddr (cddddr ,disease))))))
(defmacro codes (disease)
`(car (cddr (cddddr (cddddr (cddddr ,disease))))))
(defmacro reserve1 (disease)
`(car (cdddr (cddddr (cddddr (cddddr ,disease))))))
(defmacro reserve2 (disease)
`(car (cddddr (cddddr (cddddr (cddddr ,disease))))))
(defmacro reserve3 (disease)
`(car (cdr (cddddr (cddddr (cddddr (cddddr ,disease)))))))
(defmacro reserve4 (disease)
`(car (cddr (cddddr (cddddr (cddddr (cddddr ,disease)))))))
(defmacro reserve4 (disease)
`(car (cdddr (cddddr (cddddr (cddddr (cddddr ,disease)))))))
(defmacro reserve5 (disease)
`(car (cddddr (cddddr (cddddr (cddddr (cddddr ,disease)))))))
(defmacro prop-symptom (propl) `(car ,propl))
(defmacro prop-property (propl) `(car (cdr ,propl)))
(defmacro prop-value (propl) `(car (cddr ,propl)))
(defmacro make-name (&rest args)
`(intern (format nil "~a" ,@args)))
;******* constructors *********
(defun make-dd () (list () () ()))
(defun make-disease () (list () () () () ()
() () () () ()
() () () () ()
() () () () ()))
;******** menus *********
(defun make-it ()
(read-in)
(top-round))
(defun top-round ()
(format t "~%main~%")
(funcall
(make-menu '(work-on-dd work-on-diseases work-on-slots
general-routines
search-and-analyse
save-work stop-all))))
(defun stop-all () (break))
(defun save-work ()
(save-dd) (save-diseases))
(defun work-on-dd ()
(loop (funcall (make-menu '(show-a-dd show-all-dd
make-a-dd delete-a-dd clear-dd
make-dd-from-diseases
make-diseases-from-dd
go-back)))))
(defun work-on-diseases ()
(loop (funcall (make-menu '(add-a-disease delete-a-disease
change-a-disease find-it change-all-instances
set-disease-properties
show-a-disease show-all-diseases show-a-full-disease
search-a-disease-incremental
go-back)))))
(defun work-on-slots ()
(loop (funcall (make-menu '(add-to-existing-slot delete-slot
collect-and-sort-symptoms find-it
sort-symbols
go-back)))))
(defun general-routines ()
(loop (funcall (make-menu '(collect-and-sort-symptoms sort-symbols
find-it change-all-instances
print-list-to-file
go-back)))))
(defun search-and-analyse ()
(loop (funcall (make-menu '(search-a-disease-incremental
difference-analysis
check-the-age-group
print-list-to-file
go-back)))))
(defun go-back () (top-round))
;************ make dd from diseases *****************
; checks every symptom in the slots
; clinical-findings
; lab-findings
; rx-findings
; adds the name fo a disease to the differential-struct
; or builds a new differential-struct
(defun make-dd-from-diseases ()
(let ((d nil) (slots '(clinical-symptoms lab-findings rx-findings)))
(dolist (structnam *disease-list*)
(setf d (get-struct *all-disease* structnam 'name))
(PRINT structnam)
(dolist (s slots)
(check-slot s d)))))
(defun check-slot (slot dise)
(let ((vall (get-slot-value slot dise)))
(cond ((null vall) nil)
(t (dolist (v (setf vall (make-sure-list vall)))
(if (member v *dd-list*) (add-dd v dise)
(new-dd v dise slot)))))))
; creates a new differential
(defun new-dd (sy dis slo)
(let ((dd (make-dd)))
(cond ((null sy) nil)
(t
(setf *dd-list* (add-to-list *dd-list* sy))
(setf (symptom dd) sy)
(setf (diseases dd) (name dis))
(setf (d-slot dd) slo)
(setf *all-dd* (add-to-list *all-dd* dd))))))
; adds the disease-name to an existing differential
(defun add-dd (sy dis)
(let ((struct (get-struct *all-dd* sy 'symptom)))
(if (null struct) (error "discrepancy between *dd-list* and *all-dd"))
(cond ((null sy) nil)
(t
(setf *all-dd* (delete-from-list *all-dd* struct))
(cond ((null (diseases struct))
(setf struct (set-slot-value struct 'diseases (name dis))))
((listp (diseases struct))
(if (member (name dis) (diseases struct)) nil
(setf struct (set-slot-value struct 'diseases
(cons (name dis) (diseases struct))))))
((atom (diseases struct))
(if (equal (name dis) (diseases struct)) nil
(setf struct (set-slot-value struct 'diseases
(cons (name dis) (list (diseases struct))))))))
(setf *all-dd* (add-to-list *all-dd* struct))))))
;*********** make-diseases-from-dd *****************
; makes disease-structs from differentials
(defun make-diseases-from-dd ()
(let ((struct nil))
(dolist (sym *dd-list*)
(setf struct (get-struct *all-dd* sym 'symptom)) ;dd-symptom
(cond ((null struct)
(format t "~%discrepancy between *disease-list* and *all-disease*"))
(t (update-diseases-with-dd-symptom struct))))))
(defun update-diseases-with-dd-symptom (struct)
(let ((dis nil))
(PRINT (SYMPTOM STRUCT))
(dolist (act-dis (make-sure-list (diseases struct)))
(setf dis (get-struct *all-disease* act-dis 'name))
(cond ((null (symptom struct)) nil)
((null dis) (new-disease-from-dd
act-dis (symptom struct) (d-slot struct)))
(t (old-disease-from-dd dis (symptom struct) (d-slot struct)))))))
; makes a new disease
(defun new-disease-from-dd (dis sym sl)
(let ((str (make-disease)))
(setf sym (make-sure-list sym))
(if (null sl) (setf sl 'clinical-symptoms))
(setf (name str) dis) ; set name
(setf str (set-slot-value str sl sym)) ; set symptom ins slot sl
(setf *all-disease* (add-to-list *all-disease* str))
(setf *disease-list* (add-to-list *disease-list* dis))))
; adds the symptom to an existing disease-struct
(defun old-disease-from-dd (dis sym slot)
(let ((vall nil))
(cond ((null sym) nil)
(t (if (null slot) (setf slot 'clinical-symptoms))
(setf vall (get-slot-value slot dis))
(cond ((null vall)
(setf *all-disease* (delete-from-list *all-disease* dis))
(setf dis (set-slot-value dis slot (list sym)))
(setf *all-disease* (add-to-list *all-disease* dis)))
((listp vall)
(if (member sym vall) nil (old-diseases2 dis sym slot)))
((atom vall)
(if (equal sym vall) nil (old-diseases2 dis sym slot)))
(t nil))))))
(defun old-diseases2 (dis sym slot)
(let ((vall nil))
(setf *all-disease* (delete-from-list *all-disease* dis))
(setf vall (get-slot-value slot dis))
(setf vall (make-sure-list vall))
(setf vall (cons sym vall))
(setf dis (set-slot-value dis slot vall))
(setf *all-disease* (add-to-list *all-disease* dis))))
;****** find any word in any slot *************
(defun find-it ()
(let ((fi nil))
(setf *struct* nil)
(format t "~%FIND~%")
(setf fi (ask-for-which))
(find-it-helper *all-disease* *disease-slots* fi)
(cond ((null *struct*)
(find-it-helper *all-dd* *dd-slots* fi)
(cond ((null *struct*) (format t "~%sorry nothing found~%"))
(t (format t "~%found it in dd~%"))))
(t (format t "~%found it in diseases~%")))
(print-list *struct*)))
(defun find-it-helper (struct-list slot-list what)
(let ((slot-value nil))
(dolist (dis (setf struct-list (make-sure-list struct-list)))
(dolist (slot (setf slot-list (make-sure-list slot-list)))
(setf slot-value (get-slot-value slot dis))
(cond ((null slot-value) nil)
((atom slot-value) (if (equal what slot-value)
(setf *struct* (cons (name dis) *struct*))))
((listp slot-value) (if (member what slot-value)
(setf *struct* (cons (name dis) *struct*)))))))))
;******** disease work **************
; database-function 'add
(defun add-a-disease ()
(let ((temp nil) (stemp nil))
(format t "~%DISEASE - ADD")(terpri)
(setf temp (ask-for-which))
(cond ((member temp *disease-list*)(format t "disease exists !"))
(t (setf *disease-list* (add-to-list *disease-list* temp))
(setf stemp (make-disease))
(setf (name stemp) temp)
(setf stemp (fill-slots stemp))
(setf *all-disease* (add-to-list *all-disease* stemp))
))))
; database-function 'delete
(defun delete-a-disease ()
(let ((temp nil))
(format t "~%DISEASE - DELETE")(terpri)
(setf temp (ask-for-which))
(delete-helper temp)))
(defun delete-helper (temp)
(let ((del nil))
(cond ((not (member temp *disease-list*))
(format t "disease does not exist !"))
(t (setf *disease-list* (delete-from-list *disease-list* temp))
(setf del (get-struct *all-disease* temp 'name))
(setf *all-disease* (delete-from-list *all-disease* del))
))))
; database-function 'change
(defun change-a-disease ()
(let ((which nil) (struct nil))
(format t "~%DISEASE-CHANGE~%")
(setf which (ask-for-which))
(cond ((member which *disease-list*)
(setf struct (get-struct *all-disease* which 'name))
(format t "~%old values for ~a~%" which)
(print-disease struct)
(delete-helper which)
(change-helper struct)
(setf *all-disease* (add-to-list *all-disease* struct))
(setf *disease-list* (add-to-list *disease-list* (name struct))))
(t (format t "~%cannot find ~a in disease-list~%" which)))))
(defun change-helper (struct)
(let ((success nil) (oval nil) (slot-contains nil))
(loop
(format t "~%value to change (stop with nil) : ")
(setf success nil)
(setf oval (read))
(cond ((null oval) (return struct))
(t (dolist (sl *disease-slots*)
(setf slot-contains (get-slot-value sl struct))
(cond ((null slot-contains) nil)
((atom slot-contains)
(cond ((equal oval slot-contains)
(setf success 'ok)
(change-helper2 struct sl slot-contains oval))))
((listp slot-contains)
(cond ((member oval slot-contains)
(setf success 'ok)
(change-helper2 struct sl slot-contains oval)))))
(if (equal success 'ok) (return struct))))))))
(defun change-helper2 (str sl slc oval)
(let ((nval nil))
(progn
(format t "~%new value for ~a : " oval)
(setf nval (read))
(if (atom slc) (setf slc nval))
(if (listp slc) (setf slc (cons nval (delete oval slc))))
(set-slot-value str sl slc)
str)))
;*********** change-all-instances **************
(defun change-all-instances ()
(let ((newvalue nil) (oldvalue nil))
(format t "~%change all instances")
(format t "~%old value: ")
(setf oldvalue (read))
(cond ((null oldvalue) (return))
(t (format t "~%new value: ")
(setf newvalue (read))))
(cond ((null newvalue) nil)
(t (change-all-instances-helper oldvalue newvalue
*all-disease* *disease-list* *disease-slots*)
(change-all-instances-helper oldvalue newvalue
*all-dd* *dd-list* *dd-slots*)))))
(defun change-all-instances-helper
(oldvalue newvalue struct-list name-list slot-list)
(let ((slot-contains nil) (struct nil))
(dolist (structnam name-list)
(setf struct (get-struct struct-list structnam 'name))
(cond ((null struct)
(format t "~%error in change/inst-help ~a~%" structnam))
(t
(setf struct-list (delete-from-list struct-list struct))
(dolist (sl slot-list)
(setf slot-contains (get-slot-value sl struct))
(cond ((null slot-contains) nil)
((atom slot-contains) (if (equal slot-contains oldvalue)
(setf struct (set-slot-value struct sl newvalue))))
((listp slot-contains)
(if (member oldvalue slot-contains)
(setf struct (set-slot-value struct sl
(setf slot-contains (cons newvalue
(delete oldvalue slot-contains)))))))))
(setf struct-list (add-to-list struct-list struct)))))))
;******* search-a-disease-incremental *********
; search the database (logical 'and)
(defun search-a-disease-incremental ()
(let ((dd *disease-list*) (ant nil))
(setf *symptom-list* nil) (setf *probable-diseases* nil)
(loop
(format t "~%DD-SEARCH") (terpri)
(if (atom dd) (format t "~%last disease : ~a" dd)
(if (< 30 (length dd))
(format t "~%more than 30 diseases left")
(format t "remaining diseases ~%~a" dd)))
(terpri)
(format t "~%give me a symptom (nil = stop, new = again)~%")
(setf ant (ask-for-which))
(cond ((null ant) (setf *probable-diseases* dd) (return))
((eql 'new ant) (setf dd *disease-list* ant nil)
(setf *symptom-list* nil) (setf *probable-diseases* nil))
(t (setf dd (search-helper ant dd 's-and))))
)))
(defun search-helper (ant dd afunc)
(let ((act nil))
(cond ((equal ant nil) nil)
((member ant *dd-list*)
(setf *symptom-list* (add-to-list *symptom-list* ant))
(setf act (get-struct *all-dd* ant 'symptom))
(cond ((equal (symptom act) ant)
(if (listp (diseases act))
(setf dd (funcall afunc dd (diseases act)))
(setf dd (diseases act))))
(t (format t "~%symptom ~a not equal in struct ~a~%"
ant (symptom act)))))
(t (format t "~%symptom is not in dd-list~%")))
dd))
(defun s-and (dd diseases)
(my-intersection dd diseases))
(defun s-or (dd diseases)
(union dd diseases))
(defun s-not (dd diseases)
(set-difference dd diseases))
;******* print functions *********
(defun print-dd (struct)
(cond ((null struct) (format t "sorry, no dd to print !")(terpri))
(t (terpri) (format t "symptom : ~a" (symptom struct))
(terpri) (format t "diagnoses: ")(terpri)
(print-list (diseases struct)))))
(defun print-to-file (text file)
(dolist (x text)
(princ x file) (terpri file)))
(defun print-list-to-file ()
(let ((nam nil) (fp nil) (ll nil))
(format t "~%filename : ")
(setf nam (read))
(format t "~%list : ")
(setf ll (eval (read)))
(setf fp (open nam :direction :output))
(dolist (x (setf ll (make-sure-list ll)))
(princ x fp) (terpri fp))
(close fp)))
(defun print-list (l)
(setf *line-cnt* 0)
(cond ((null l) (format t "sorry, no list to print !")(terpri))
((atom l) (print l) (terpri))
(t (dolist (x l) (print-and-count-lines x))
(wait-for-answer)
(terpri))))
(defun print-and-count-lines (lin)
(cond ((>= *line-cnt* 15) (wait-for-answer)
(print lin) (setf *line-cnt* 0))
(t (print lin) (setf *line-cnt* (+ 1 *line-cnt*)))))
(defun wait-for-answer ()
(read-char))
(defun print-disease (struct)
(let ((ms nil))
(cond ((null struct) (format t "~%sorry, no disease to print ") (terpri))
(t (dolist (m *disease-slots*)
(setf ms (get-slot-value m struct))
(cond ((null ms) nil)
(t (terpri)(princ m) (princ " : ")
(princ ms))))))
(terpri)))
(defun print-full-disease (struct)
(cond ((null struct) (format t "~%sorry, no disease to print ") (terpri))
(t (dolist (m *disease-slots*)
(terpri)(princ m) (princ " : ")
(princ (get-slot-value m struct)))))
(terpri))
;********* word-root functions *******
; don't use it on an PC, takes hell of time
(defun make-word-root-list ()
(let ((*all-symptoms* (read-list-from-file "asymptom.txt")))
(dolist (x *all-symptoms*)
(checklist x (get-single-words x)))
(write-list-to-file *word-root-list* "asymptom.rot")))
(defun get-single-words (word)
(let ((wname (symbol-name word)) (word-list nil) (input nil))
(setf word-list (substitute #\ #\- wname))
(setf input (make-string-input-stream word-list))
(do ((x (read input nil) (read input nil))
(sentence nil))
((not x) (return (reverse sentence)))
(push x sentence))))
(defun checklist (full-word word)
(let ((struct (get-hlist (car word))))
(if (null struct) (put-hlist full-word (car word))
(if (setf struct (checklist2 full-word (make-sure-list struct)))
(put-hlist struct (car word))))))
(defun checklist2 (full-word struct)
(dolist (x struct)
(if (eq x full-word) (return)))
(setf struct (append (make-sure-list struct) (make-sure-list full-word)))
struct)
(defun put-hlist (wlist nkey)
(let ((temp nil))
(setf temp (assoc nkey *word-root-list*))
(setf *word-root-list* (delete-from-list *word-root-list* temp))
(setf *word-root-list* (add-to-list *word-root-list*
(append (list nkey) (make-sure-list wlist))))))
(defun get-hlist (nkey)
(cdr (assoc nkey *word-root-list*)))
;********* menu /display **************
(defun make-menu (li)
(cond ((null li) nil)
(t (display-menu li))))
(defun display-menu (li)
(let ((long (length li)))
(cond ((> long 29) (format t "~%menu with ~a entries too long!~%" long))
((> long 15) (display-single-menu li long))
(t (display-single-menu li long)))))
(defun display-single-menu (li long)
(terpri)
(dotimes (x long)
(format t "~%~a ~a" (1+ x) (nth x li)))
(get-numbered-answer li long))
(defun display-double-menu (li long)
(let ((half (round (+ 0.5 (/ long 2)))))
(dotimes (x (1+ half))
(cond ((null (nth x li)) nil)
(t (format t "~&~D ~A~36t" (1+ x) (nth x li))))
(cond ((null (nth (1+ (+ x half)) li)) nil)
(t (format t "~D ~A" (+ 2 (+ x half)) (nth (1+ (+ x half)) li)))))
(get-numbered-answer li long)))
(defun get-numbered-answer (li long)
(let ((ans nil))
(format t "~%Enter a number between 1 and ~a~%" long)
(setf ans (read))
(cond ((not (numberp ans)) (get-numbered-answer li long))
((null ans) (get-numbered-answer li long))
((or (< long ans) (> 0 ans)) (get-numbered-answer li long))
(t (nth (1- ans) li)))))
;******** file functions *********
(defun read-in () (read-diseases) (read-dd)
(read-symptoms))
(defun read-dd ()
(format t "~%reading dd-files~%")
(setf *all-dd* (read-list-from-file "dd.txt"))
(format t "~%constructing *dd-list*~%")
(setf *dd-list* (get-cars *all-dd*)))
(defun save-dd ()
(format t"~%saving dd-files~%")
(write-list-to-file *all-dd* "dd.txt"))
(defun read-diseases ()
(format t"~%reading disease-files~%")
(setf *all-disease* (read-list-from-file "diseases.txt"))
(format t "~%constructing *disease-list*~%")
(setf *disease-list* (get-cars *all-disease*)))
(defun save-diseases ()
(format t"~%saving disease-files~%")
(write-list-to-file *all-disease* "diseases.txt"))
(defun read-symptoms ()
(format t"~%reading symptom-files")
(setf *all-symptoms* (read-list-from-file "asymptom.txt"))
(setf *word-root-list* (read-list-from-file "asymptom.rot")))
(defun read-list-from-file (filename)
(let ((listname nil)
(fp (open filename :direction :input)))
(progn
(do* ((ex nil)
(ex (read fp) (read fp)))
((null ex) (close fp))
(setf listname (cons ex listname)))
listname)))
(defun write-list-to-file (listname filename)
(let ((listname (make-sure-list listname))
(fp (open filename :direction :output)))
(dolist (x listname)
(print x fp))
(close fp)))
;******** slot functions *********
; access and fill the subparts of the disease-struct
(defun fill-slots (struct)
(let ((antw nil) (tx (cons 'return (cdr *disease-slots*))))
(loop
(setf antw (make-menu tx))
(cond ((equal antw 'return) (return struct))
((member antw *disease-slots*)
(setf struct (put-slot struct antw)))
(t (format t "error: non-existing slot in fill-slots !"))))))
(defun put-slot (struct antw)
(let ((temp (make-sure-list (input-list))))
(set-slot-value struct antw temp)))
(defun set-slot-value (struct antw temp)
(progn
(case antw
(name (setf (name struct) temp))
(age-groups (setf (age-groups struct) temp))
(sex-predominance (setf (sex-predominance struct) temp))
(clinical-symptoms (setf (clinical-symptoms struct) temp))
(lab-findings (setf (lab-findings struct) temp))
(rx-findings (setf (rx-findings struct) temp))
(sites (setf (sites struct) temp))
(therapy (setf (therapy struct) temp))
(follow-up (setf (follow-up struct) temp))
(prognosis-and-complications
(setf (prognosis-and-complications struct) temp))
(literature (setf (literature struct) temp))
(diff-diag (setf (diff-diag struct) temp))
(general-description (setf (general-description struct) temp))
(property-slot (setf (property-slot struct) temp))
(codes (setf (codes struct) temp))
(reserve1 (setf (reserve1 struct) temp))
(reserve2 (setf (reserve2 struct) temp))
(reserve3 (setf (reserve3 struct) temp))
(reserve4 (setf (reserve4 struct) temp))
(reserve5 (setf (reserve5 struct) temp))
;(clinical-symptoms-props (setf (clinical-symptoms-props struct) temp))
;(lab-findings-props (setf (lab-findings-props struct) temp))
;(rx-findings-props (setf (rx-findings-props struct) temp))
(symptom (setf (symptom struct) temp))
(diseases (setf (diseases struct) temp))
(d-slot (setf (d-slot struct) temp)))
struct))
(defun get-slot-value (antw struct)
(let ((result nil))
(progn
(case antw
(name (setf result (name struct)))
(age-groups (setf result (age-groups struct)))
(sex-predominance (setf result (sex-predominance struct)))
(clinical-symptoms (setf result (clinical-symptoms struct)))
(lab-findings (setf result (lab-findings struct)))
(rx-findings (setf result (rx-findings struct)))
(sites (setf result (sites struct)))
(therapy (setf result (therapy struct)))
(follow-up (setf result (follow-up struct)))
(prognosis-and-complications
(setf result (prognosis-and-complications struct)))
(literature (setf result (literature struct)))
(diff-diag (setf result (diff-diag struct)))
(general-description (setf result (general-description struct)))
(property-slot (setf result (property-slot struct)))
(codes (setf result (codes struct)))
(reserve1 (setf result (reserve1 struct)))
(reserve2 (setf result (reserve2 struct)))
(reserve3 (setf result (reserve3 struct)))
(reserve4 (setf result (reserve4 struct)))
(reserve5 (setf result (reserve5 struct)))
;(clinical-symptoms-props (setf result (clinical-symptoms-props struct)))
;(lab-findings-props (setf result (lab-findings-props struct)))
;(rx-findings-props (setf result (rx-findings-props struct)))
(symptom (setf result (symptom struct)))
(diseases (setf result (diseases struct)))
(d-slot (setf result (d-slot struct))))
result)))
(defun input-list ()
(let ((temp nil))
(progn
(format t "~%list-input (terminate with nil):~%")
(do ((input (read-sentence) (read-sentence))) ;start
((equal nil input) temp) ; end
(setf temp (append input temp)))))) ;body
; works on a part of a disease-struct
; 'delete' function
(defun delete-slot ()
(let ((dis nil))
(format t "~%DISEASE-DELETE-SLOT~%")
(format t "~%INPUT DISEASE~%")
(setf dis (ask-for-which))
(cond ((null dis) nil)
((member dis *disease-list*)
(delete-slot-helper
(get-struct *all-disease* dis 'name)))
(t (format t "~%unknown error in delete-slot ~a~%" dis)))))
(defun delete-slot-helper (struct)
(let ((slot nil) (tempstruct nil))
(loop
(format t "~%ACTUAL VALUES~%")
(print-disease struct)
(format t "~%INPUT SLOT~%")
(setf slot (make-menu (cons 'return *disease-slots*)))
(cond ((equal 'return slot)
(delete-from-list *all-disease* tempstruct)
(setf *all-disease* (add-to-list *all-disease* struct))
(return))
(t (setf struct (set-slot-value struct slot nil)))))))
; works on a part of the disease-struct
; 'add' function
(defun add-to-existing-slot ()
(let ((dis nil))
(format t "~%DISEASE-ADD-TO-SLOT~%")
(format t "~%INPUT DISEASE~%")
(setf dis (ask-for-which))
(cond ((null dis) nil)
((member dis *disease-list*)
(add-to-existing-slot-helper
(get-struct *all-disease* dis 'name)))
(t (format t "~%unknown error in add-to-existing-slot ~a~%" dis)))))
(defun add-to-existing-slot-helper (struct)
(let ((slot nil) (tempstruct nil))
(loop
(format t "~%ACTUAL VALUES~%")
(print-disease struct)
(format t "~%INPUT SLOT~%")
(setf slot (make-menu (cons 'return *disease-slots*)))
(cond ((equal 'return slot)
(delete-from-list *all-disease* tempstruct)
(setf *all-disease* (add-to-list *all-disease* struct))
(return))
(t (setf struct (add-to-existing-slot-helper2 slot struct)))))))
(defun add-to-existing-slot-helper2 (slot struct)
(let ((temp nil))
(format t "~%ACTUAL VALUES FOR SLOT ~a~%" slot)
(print (get-slot-value slot struct)) (terpri)
(setf temp (input-list))
(set-slot-value struct slot (append (get-slot-value slot struct) temp))))
; because the file-save did not work with symbols and properties
; I put the properties in a special slot of a disease-struct
(defun set-disease-properties ()
(let ((which nil))
(format t "~%DISEASE-PROPERTIES~%")
(format t "~%INPUT DISEASE~%")
(setf which (ask-for-which))
(cond ((null which) nil)
((member which *disease-list*)
(set-disease-properties-helper
(get-struct *all-disease* which 'name)))
(t (format t "~%cannot find ~a in disease-list~%" which)))))
(defun set-disease-properties-helper (struct)
(format t "~%values for ~a~%" (name struct))
(delete-helper (name struct))
(setf struct (change-properties struct))
(setf *all-disease* (add-to-list *all-disease* struct))
(setf *disease-list* (add-to-list *disease-list* (name struct))))
(defun change-properties (struct)
(let ((slot 'property-slot) (symp nil) (pr nil)
(val nil) (x nil))
(loop
(print-disease struct)
(format t"~%symptom :~%")
(setf symp (read))
(if (null symp) (return struct))
(format t "~%property :~%")
(setf pr (make-menu (cons 'return *prop-list*)))
(if (equal 'return pr) (return struct))
(format t "~%property-value for symbol ~a , property ~a.~%" symp pr)
(setf val (read))
(if (or (null val) (equal 'return val)) (return struct))
(setf x (cons (list symp pr val)(get-slot-value slot struct)))
(setf struct (set-slot-value struct slot x)))))
;******* collecting and sorting **********
; collects all existing symptoms and writes it to file
; 'asymptom.txt'
(defun collect-and-sort-symptoms ()
(let ((slots '(clinical-symptoms lab-findings rx-findings))
(dis nil))
(setf *all-symptoms* '(cough fever))
(dolist (structnam *disease-list*)
(setf dis (get-struct *all-disease* structnam 'name))
(cond ((null dis) (format t "~%discrepancy *all-disease* / *disease-list*~%"))
(t (do-slots slots dis))))
(setf *all-symptoms* (sort-them *all-symptoms*))
(format t "~%writing to symptoms to disk")
(write-list-to-file *all-symptoms* "asymptom.txt")
(format t "~%saved symptoms~%")))
(defun do-slots (slots dis)
(let ((slot-values nil))
(dolist (slot slots)
(setf slot-values (get-slot-value slot dis))
(cond ((null slot-values) nil)
(t (do-slot-values slot-values))))))
(defun do-slot-values (slot-values)
(let ((slot-values (make-sure-list slot-values)))
(dolist (sym slot-values)
(cond ((null sym) nil) ;empty slot
((member sym *all-symptoms*) nil)
(t (setf *all-symptoms* (cons sym *all-symptoms*)))))))
;****** general functions ***************
; sorts any list of symbols by their 'alphabetic' rank
(defun sort-symbols ()
(let ((lst nil))
(format t "~%input symbol-list~%")
(setf lst (read))
(cond ((member lst '(*all-disease* *all-dd*))
(format t "~% invalid value"))
(t (sort-them (eval lst))))))
(defun sort-them (sylist)
(let ((rst nil))
(progn
(setf *all-string-list* nil)
(dolist (x (setf sylist (make-sure-list sylist)))
(setf *all-string-list* (cons (zap-to-string x) *all-string-list*)))
(setf *all-string-list* (sort *all-string-list* #'string>))
(dolist (x (setf *all-string-list* (make-sure-list *all-string-list*)))
(setf rst (cons (make-name x) rst)))
rst)))
; read an input terminated by 'nil
; and return the symbols
(defun read-sentence ()
(let ((input nil) (input2 nil))
(setf input2 (string-trim ".,?!" (read-non-empty-line)))
(setf input (make-string-input-stream input2))
(do ((word (read input nil)(read input nil))
(sentence nil))
((not word) (return (reverse sentence)))
(push word sentence))))
; ask
(defun ask-for-which ()
(format t "~%which one please ?")
(read))
; if its no list --> then make one
(defun make-sure-list (tmp)
(progn
(cond ((atom tmp) (setf tmp (list tmp)))
((listp tmp) nil)
(t (format t"~%error making list from ~a~%" tmp)))
tmp))
; ignore empty inputs
(defun read-non-empty-line ()
(let ((result nil))
(loop
(setq result (read-line)) (if (= (length result) 0) nil
(return result)))))
; get the first symbol of every list in a list
(defun get-cars (ll)
(let ((res nil))
(dolist (x ll)
(setf res (cons (car x) res)))
res))
; Common lisp function
(defun remove-duplicates (lsta)
(let ((result nil))
(dolist (x lsta)
(cond ((member x result) nil)
(t (setf result (cons x result)))))
result))
;**** show functions ******
(defun show-a-dd ()
(print-dd (get-struct
*all-dd* (ask-for-which) 'symptom)))
(defun show-all-dd ()
(print-list *dd-list*))
(defun show-a-disease ()
(print-disease (get-struct *all-disease* (ask-for-which)
'name)))
(defun show-a-full-disease ()
(print-full-disease (get-struct *all-disease* (ask-for-which)
'name)))
(defun show-all-diseases ()
(print-list *disease-list*))
;********** struct-operations ************
; accessor for diseases and differentials
; could be replaced by a hash-list or files or ...
; as long as every call goes by these functions,
; the real type of the list is not important and easy to change
(defun get-struct (struct-list which slot-name)
(dolist (m (setf struct-list (make-sure-list struct-list)))
(if (equal (get-slot-value slot-name m) which)
(return m))))
(defun delete-from-list (struct-list which)
(setf struct-list (delete which struct-list)))
(defun add-to-list (struct-list what)
(setf struct-list (cons what struct-list)))
;************** differentials ****************
; database-function 'create'
(defun make-a-dd ()
(let ((tt nil) (ddtemp nil))
(format t "~%Differentials Entry")
(format t "~%-------------------")
(terpri)
(format t "~%DD - Symptom : ")
(setf tt (read))
(cond ((null tt) nil)
((member tt *dd-list*)
(format t "Symptom exists already !"))
(t (setf *dd-list* (add-to-list *dd-list* tt))
(setf ddtemp (make-dd)) (setf (symptom ddtemp) tt)
(setf (diseases ddtemp) (input-dd-diseases))
(format t "~%slot :~%")
(setf (d-slot ddtemp) (make-menu *disease-slots*))
(setf *all-dd* (add-to-list *all-dd* ddtemp))))))
(defun input-dd-diseases ()
(let ((temp nil))
(progn
(format t "~%DD - diseases : ")
(do ((input (read-sentence) (read-sentence))) ;start
((equal nil input) (if (atom temp) (list temp))
temp) ; end
(setf temp (append input temp))) ;body
(if (atom temp) (list temp) temp))))
; database-function 'delete' for differentials
(defun delete-a-dd ()
(let ((del nil) (del2 nil))
(format t "~%DELETE DD :~%")
(setf del (ask-for-which))
(cond ((member del *dd-list*)
(setf *dd-list* (delete-from-list *dd-list* del))
(setf del2 (get-struct *all-dd* del 'symptom))
(setf *all-dd* (delete-from-list *all-dd* del2)))
(t (format t "~%unable to delete ~a~%" del)))))
; in case you did something wrong
(defun restore-disease-list ()
(setf *disease-list* nil)
(setf *disease-list* (get-cars *all-disease*)))
(defun restore-dd-list ()
(setf *dd-list* nil)
(setf *dd-list* (get-cars *all-dd*)))
;********* analyse search-results ***********
; display the difference in symptoms of 2 diseases
; the result of the last search is stored in
; the symbol *probable-diseases*
(defun difference-analysis ()
(let* ((len (length *probable-diseases*))
(symptom-array (make-array (* len len)))
(place 0) (sx nil))
;collect-all-symptoms-from-one-disease
(dolist (dis (setf *probable-diseases* (make-sure-list *probable-diseases*)))
(setf sx (collect-symps dis))
(setf (aref symptom-array place) sx)
(setf place (+ place len)))
(setf result-array (do-difference symptom-array len))
(print-result-array *probable-diseases* result-array len)))
; print-result of analysis
(defun print-result-array (pd res len)
(let ((start 0) (next -1))
(dotimes (x (* len len))
(setf next (1+ next))
(cond ((equal next len) (setf next 0) (setf start (1+ start)))
(t nil))
(format t "~%~a differs from ~a~%" (nth start pd) (nth next pd))
(print (aref res x))
(format t "~% press any key to continue~%") (wait-for-answer)
)))
(defun do-difference (symptom-array len)
(let ((r-array (make-array (* len len))) (start nil))
(progn
(dotimes (x len)
(setf start (* x len))
(dotimes (y len)
(setf (aref r-array (+ start y))
(set-difference (aref symptom-array start)
(aref symptom-array (* len y))))))
r-array)))
(defun collect-symps (nam)
(let ((rt nil) (temp nil)
(slot-list '(clinical-symptoms lab-findings rx-findings))
(struct (get-struct *all-disease* nam 'name)))
(dolist (slot slot-list)
(setf temp (get-slot-value slot struct))
(if (not (null temp)) (setf rt (append rt temp))))
rt))
;******** analysis v 28/06/89 ***************
; does the patient match the age-group of the diseases ?
(defun check-the-age-group ()
(let ((temp-list *probable-diseases*) (age (get-the-age-group))
(dis-struct nil) (range nil))
(setq *age-probable* nil *no-age* nil *out-of-age* nil)
(dolist (dis (setf temp-list (make-sure-list temp-list)))
(setf dis-struct (get-struct *all-disease* dis 'name))
(setf range (get-slot-value 'age-groups dis-struct))
(cond ((null range)
(setq *no-age* (cons (name dis-struct) *no-age*)))
((in-range age range)
(setf *age-probable* (cons (name dis-struct) *age-probable*)))
(t (setq *out-of-age* (cons (name dis-struct) *out-of-age*)))))
(print-age-results)))
(defun print-age-results ()
(format t "~%continue with <RETURN>~%")
(if (null *age-probable*) nil (print-age-probable))
(if (null *no-age*) nil (print-no-age))
(if (null *out-of-age*) nil (print-out-of-age)))
(defun print-age-probable ()
(format t "~%diseases with congruent age-groups are :~%")
(print-list (remove-duplicates *age-probable*))
(wait-for-answer))
(defun print-no-age ()
(format t "~%diseases with missing age-groups are :~%")
(print-list (remove-duplicates *no-age*))
(wait-for-answer))
(defun print-out-of-age ()
(format t "~%diseases outside the current age-groups are :~%")
(print-list (remove-duplicates *out-of-age*))
(wait-for-answer))
(defun in-range (age range) ; missing age-check for weeks/months
(do ((age-list range (cddr age-list)))
((null age-list) nil)
(cond ((and (>= age (first age-list)) (<= age (second age-list)))
(return t))
(t nil))))
(defun get-the-age-group ()
(let ((age nil))
(format t "~%DISEASE-ANALYSIS~%")
(format t "~%input age of patient~%")
(setf age (read))
(cond ((numberp age) age)
(t (get-the-age-group)))))
;****** xlisp functions **********
(defun substitute (new old s &key (test #'eql))
(case (type-of s)
(string (string:substitute new old s :test test))
(cons (subst new old s :test test))
))
(defun my-intersection (x y)
(let ((result nil))
(dolist (a (make-sure-list x))
(if (member a y)
(setf result (cons a result))))
result))
(defun set-difference (x y &key (test #'eql))
(if x
(let*
((uh (car x))
(recursion
(set-difference (remove uh x :test test)
(remove uh y :test test) :test test)))
(if (member uh y :test test)
recursion
(cons uh recursion)))))
(defun union (s1 s2 &key (test #'eql))
(if s1
(adjoin (car s1) (union (cdr s1) s2 :test test) :test test)
s2))
(defun string:substitute (new old string &key (test #'eql))
(let ((big (length string)))
(if (> big 0)
(dotimes (i big string)
(let ((c (char string i)))
(if (funcall test c old)
(return
(strcat (subseq string 0 i)
(char->string new)
(string:substitute new
old
(subseq string (1+ i))))))))
string)))
(defun char->string (c) (string c))
(setq *declared-globals* nil)
(defmacro defvar (variable-name &optional value)
`(progn
(if (not (member ',variable-name *declared-globals*))
(push ',variable-name *declared-globals*))
(setq ,variable-name ,value)
(putprop ',variable-name 'variable 'binding)
))
(defmacro defconstant (constant-name &optional value)
`(progn
(if (not (member ',constant-name *declared-globals*))
(push ',constant-name *declared-globals*))
(setq ,constant-name ,value)
(putprop ',constant-name 'constant 'binding)
))
(defvar *declared-globals*)
;******** list / string manipulation ************
; copied from Larry Mulcahy UL.ARC
(defun list-to-string (l)
(if (null l)
""
(if (equal (length l) 1)
(symbol-name (car l))
(concatenate 'string
(symbol-name (car l))
" "
(list-to-string (cdr l))))))
(defun zap-to-string (uh)
(cond
((listp uh) (list-to-string uh))
((symbolp uh) (symbol-name uh))
((numberp uh) (number-to-string uh))
(t (string uh))))
(defun list-to-string (ll)
(cond ((null ll) "")
((equal (length ll) 1) (zap-to-string (car ll)))
(t (concatenate 'string (zap-to-string (car ll)) " "
(list-to-string (cdr ll))))))
(defun number-to-string (n)
(case (type-of n)
(float (if (> (abs n) 100000.0)
(primitive-number-to-string (round n))
(if (< (abs n) 1.0) (format nil "~F" (trim-float n 8))
(format nil "~F" (trim-float n 2)))))
(ratio (if (> (abs n) 100)
(number-to-string (coerce n 'float))
(multiple-value-bind
(whole fraction) (truncate n)
(if (= fraction 0) (format nil "~D" whole)
(format nil "~D-~D" whole fraction)))))
(otherwise (primitive-number-to-string n))))
(defun primitive-number-to-string (n)
(let ((stream (make-string-output-stream)))
(princ n stream)
(get-output-stream-string stream)))
(defun trim-float (x digits)
(let ((magnitude (expt 10 digits)))
(/ (fround (* x magnitude)) magnitude)))